/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.statemachine.editpart;

import java.util.Iterator;

import org.eclipse.draw2d.IFigure;
import org.eclipse.uml2.uml.AnyReceiveEvent;
import org.eclipse.uml2.uml.Behavior;
import org.eclipse.uml2.uml.BehavioralFeature;
import org.eclipse.uml2.uml.CallEvent;
import org.eclipse.uml2.uml.ChangeEvent;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Event;
import org.eclipse.uml2.uml.LiteralString;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.SignalEvent;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.TimeEvent;
import org.eclipse.uml2.uml.Transition;
import org.eclipse.uml2.uml.Trigger;
import org.eclipse.uml2.uml.ValueSpecification;

import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.LinkNameDisplayEditPart;
import com.cea.papyrus.core.figures.StringFigure;
import com.cea.papyrus.diagram.statemachine.helper.EdgeTransitionHelper;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Property;

/**
 * Manages display of LiteralStrings kept in a Transition.
 *
 * @author David Servat
 * @since 10 apr. 07
 */
public class TransitionGuardAndAllDisplayEditPart extends LinkNameDisplayEditPart{	

	/** The guard text. */
	private String guardText;
	
	/** The triggers text. */
	private String triggersText;

	/** The effect text. */
	private String effectText;

	/** The is guard displayed. */
	private boolean isGuardDisplayed;

	/** The is effect displayed. */
	private boolean isEffectDisplayed;

	/** The is triggers displayed. */
	private boolean isTriggersDisplayed;
	
	/** The is stereotypes displayed */
	private boolean isStereotypesDisplayed;

	public TransitionGuardAndAllDisplayEditPart(GraphNode graphNode, ModelManager modelManager){
		super(graphNode,modelManager);
		element = null;
		guardText = "";
		effectText = "";
		triggersText = "";
		isGuardDisplayed = false;
		isEffectDisplayed = false;
		isTriggersDisplayed = false;
		isStereotypesDisplayed = false;
		
		getGuardAndAllDisplayProperties(graphNode);
	}

	public TransitionGuardAndAllDisplayEditPart(GraphNode graphNode,Element element,ModelManager modelManager){
		super(graphNode,modelManager);
		this.element = element;
		guardText = "";
		triggersText = "";
		effectText = "";
		
		getGuardAndAllDisplayProperties(graphNode);
	}
	
	/**
	 * Gets the guard and all display properties.
	 * 
	 * @param graphNode the graph node
	 */
	private void getGuardAndAllDisplayProperties(GraphNode graphNode){
		//get stereotype display property
		Property property = graphNode.getProperty(EdgeTransitionHelper.TRANSITION_DISPLAY_STEREOTYPES);
		if(property != null){
			if(property.getValue().equals(EdgeTransitionHelper.TRANSITION_DISPLAY)){
				isStereotypesDisplayed = true;
			}
			else{
				isStereotypesDisplayed = false;
			}
		}
		//get guard display property
		property = graphNode.getProperty(EdgeTransitionHelper.TRANSITION_DISPLAY_GUARD);
		if(property != null){
			if(property.getValue().equals(EdgeTransitionHelper.TRANSITION_DISPLAY)){
				if(((Transition)getUmlElement()).getGuard() != null)
					isGuardDisplayed = true;
				else{
					property.setValue(EdgeTransitionHelper.TRANSITION_NOT_DISPLAY);
					isGuardDisplayed = false;
				}
			}
			else{
				isGuardDisplayed = false;
			}
		}
		//get effect display property
		property = graphNode.getProperty(EdgeTransitionHelper.TRANSITION_DISPLAY_EFFECT);
		if(property != null){
			if(property.getValue().equals(EdgeTransitionHelper.TRANSITION_DISPLAY)){
				if(((Transition)getUmlElement()).getEffect() != null)
					isEffectDisplayed = true;
				else{
					isEffectDisplayed = false;
					property.setValue(EdgeTransitionHelper.TRANSITION_NOT_DISPLAY);
				}
			}
			else{
				isEffectDisplayed = false;
			}
		}
		//get triggers display property
		property = graphNode.getProperty(EdgeTransitionHelper.TRANSITION_DISPLAY_TRIGGERS);
		if(property != null){
			if(property.getValue().equals(EdgeTransitionHelper.TRANSITION_DISPLAY)){
				if(!((Transition)getUmlElement()).getTriggers().isEmpty())
					isTriggersDisplayed = true;
				else{
					isTriggersDisplayed = false;
					property.setValue(EdgeTransitionHelper.TRANSITION_NOT_DISPLAY);
				}
			}
			else{
				isTriggersDisplayed = false;
			}
		}
	}

	/**
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#createFigure()
	 */
	@Override
	protected IFigure createFigure(){
		if(element instanceof Transition){
			Transition transition = (Transition) element;
			
			//guard management
			if(transition.getGuard() == null)
				guardText = "";
			else{
				Constraint constraint = transition.getGuard();
				
				if(!constraint.eAdapters().contains(_adapter))
					constraint.eAdapters().add(_adapter);
				
				String stereos = "";
				Iterator it = constraint.getAppliedStereotypes().iterator();
				while(it.hasNext()){
					String st = ((Stereotype)it.next()).getName();
					st = st.substring(0, 1).toUpperCase()+st.substring(1);
					stereos += st;
				}
				if((stereos != "") && isStereotypesDisplayed)
					guardText = "\""+stereos+"\" "+((ValueSpecification)constraint.getSpecification()).stringValue();
				else
					guardText = ((ValueSpecification)constraint.getSpecification()).stringValue();
				if(guardText == null)
					guardText = "";
			}
			
			//effect management
			if(transition.getEffect() == null)
				effectText = "";
			else{
				Behavior behavior = transition.getEffect();
				
				if(!behavior.eAdapters().contains(_adapter))
					behavior.eAdapters().add(_adapter);
				
				if (behavior.getSpecification() != null) {
					// Show specification of behavior (a behavioral feature (usually an operation)
					BehavioralFeature bf = behavior.getSpecification();

					if(!bf.eAdapters().contains(_adapter))
						bf.eAdapters().add(_adapter);
					
					String stereos = "";
					Iterator it = bf.getAppliedStereotypes().iterator();
					while(it.hasNext()){
						String st = ((Stereotype)it.next()).getName();
						st = st.substring(0, 1).toUpperCase()+st.substring(1);
						stereos += st;
					}
					String lb = bf.getLabel();
					if(bf instanceof Operation)
						lb = com.cea.papyrus.umlutils.Operation.getSignature((Operation) bf, false);
					if((stereos != "") && isStereotypesDisplayed)
						effectText = "/ "+"\""+stereos+"\" "+lb;
					else
						effectText = "/ "+lb;
				}
				else{
					String stereos = "";
					Iterator it = behavior.getAppliedStereotypes().iterator();
					while(it.hasNext()){
						String st = ((Stereotype)it.next()).getName();
						st = st.substring(0, 1).toUpperCase()+st.substring(1);
						stereos += st;
					}
					if((stereos != "") && isStereotypesDisplayed)
						effectText = "/ "+"\""+stereos+"\" "+behavior.getLabel();
					else
						effectText = "/ "+behavior.getLabel();
					if (effectText == null) {
						effectText = "";	
					}
				}
			}
			
			//triggers management
			if((transition.getTriggers() == null) || transition.getTriggers().isEmpty())
				triggersText = "";
			else{
				triggersText = "";
				Iterator iter = transition.getTriggers().iterator();
				while(iter.hasNext()){
					Trigger trigger = (Trigger)iter.next();
					
					if(!trigger.eAdapters().contains(_adapter))
						trigger.eAdapters().add(_adapter);
					
					Event event = trigger.getEvent();
					if(event != null){
						if(!event.eAdapters().contains(_adapter))
							event.eAdapters().add(_adapter);
						
						String stereos = "";
						Iterator it = event.getAppliedStereotypes().iterator();
						while(it.hasNext()){
							String st = ((Stereotype)it.next()).getName();
							st = st.substring(0, 1).toUpperCase()+st.substring(1);
							stereos += st;
						}
						if((stereos != "") && isStereotypesDisplayed)
							triggersText += "\""+stereos+"\" ";
						if(event instanceof CallEvent)
							triggersText += com.cea.papyrus.umlutils.Operation.getSignature(((CallEvent)event).getOperation(), false)+", ";
						else if(event instanceof SignalEvent)
							triggersText += ((SignalEvent)event).getSignal().getName()+", ";
						else if(event instanceof AnyReceiveEvent)
							triggersText += "all, ";
						else if(event instanceof ChangeEvent){
							ChangeEvent changeEvent = (ChangeEvent)event;
							if((changeEvent.getChangeExpression() != null) && (changeEvent.getChangeExpression() instanceof LiteralString))
								triggersText += "when "+changeEvent.getChangeExpression().stringValue()+", ";
							else
								triggersText += "when "+changeEvent.getName()+", ";
						}		
						else if(event instanceof TimeEvent){
							TimeEvent timeEvent = (TimeEvent)event;
							if((timeEvent.getWhen() != null) && (timeEvent.getWhen() instanceof LiteralString))
								triggersText += timeEvent.getWhen().stringValue()+", ";
							else
								triggersText += timeEvent.getName()+", ";
						}		
					}
					else{
						triggersText += trigger.getName();
					}
				}
				triggersText = triggersText.substring(0, triggersText.length()-2);
			}
			
			//update display properties
			getGuardAndAllDisplayProperties(getGraphNode());

			String toShow = "";
			if(isTriggersDisplayed)
				toShow += triggersText;
			if(isGuardDisplayed)
				toShow += guardText;
			if(isEffectDisplayed)
				toShow += effectText;
			return new StringFigure(toShow);
		}
		else
			return new StringFigure("");
	}
	
	/**
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#refreshVisuals()
	 */
	@Override
	protected void refreshVisuals(){
		StringFigure f = (StringFigure)getFigure();
		
		if(element instanceof Transition){
			Transition transition = (Transition) element;
			
			//guard management
			if(transition.getGuard() == null)
				guardText = "";
			else{
				Constraint constraint = transition.getGuard();
				
				if(!constraint.eAdapters().contains(_adapter))
					constraint.eAdapters().add(_adapter);
				
				String stereos = "";
				Iterator it = constraint.getAppliedStereotypes().iterator();
				while(it.hasNext()){
					String st = ((Stereotype)it.next()).getName();
					st = st.substring(0, 1).toUpperCase()+st.substring(1);
					stereos += st;
				}
				if((stereos != "") && isStereotypesDisplayed)
					guardText = "\""+stereos+"\" "+((ValueSpecification)constraint.getSpecification()).stringValue();
				else
					guardText = ((ValueSpecification)constraint.getSpecification()).stringValue();
				if(guardText == null)
					guardText = "";
			}
			
			//effect management
			if(transition.getEffect() == null)
				effectText = "";
			else{
				Behavior behavior = transition.getEffect();
			
				if(behavior.eAdapters().contains(_adapter))
					behavior.eAdapters().add(_adapter);
				
				if (behavior.getSpecification() != null) {
					// Show specification of behavior (a behavioral feature (usually an operation)
					BehavioralFeature bf = behavior.getSpecification();
					
					if(!bf.eAdapters().contains(_adapter))
						bf.eAdapters().add(_adapter);
					
					String stereos = "";
					Iterator it = bf.getAppliedStereotypes().iterator();
					while(it.hasNext()){
						String st = ((Stereotype)it.next()).getName();
						st = st.substring(0, 1).toUpperCase()+st.substring(1);
						stereos += st;
					}
					String lb = bf.getLabel();
					if(bf instanceof Operation)
						lb = com.cea.papyrus.umlutils.Operation.getSignature((Operation) bf, false);
					if((stereos != "") && isStereotypesDisplayed)
						effectText = "/ "+"\""+stereos+"\" "+lb;
					else
						effectText = "/ "+lb;
				} 
				else {
					String stereos = "";
					Iterator it = behavior.getAppliedStereotypes().iterator();
					while(it.hasNext()){
						String st = ((Stereotype)it.next()).getName();
						st = st.substring(0, 1).toUpperCase()+st.substring(1);
						stereos += st;
					}
					if((stereos != "") && isStereotypesDisplayed)
						effectText = "/ "+"\""+stereos+"\" "+behavior.getLabel();
					else
						effectText = "/ "+behavior.getLabel();
					if (effectText == null) {
						effectText = "";	
					}
				}

			}
			
			//triggers management
			if((transition.getTriggers() == null) || transition.getTriggers().isEmpty())
				triggersText = "";
			else{
				triggersText = "";
				Iterator iter = transition.getTriggers().iterator();
				while(iter.hasNext()){
					Trigger trigger = (Trigger)iter.next();
					
					if(!trigger.eAdapters().contains(_adapter))
						trigger.eAdapters().add(_adapter);
					
					String stereos = "";
					Iterator it = trigger.getAppliedStereotypes().iterator();
					while(it.hasNext()){
						String st = ((Stereotype)it.next()).getName();
						st = st.substring(0, 1).toUpperCase()+st.substring(1);
						stereos += st;
					}
					if((stereos != "") && isStereotypesDisplayed)
						triggersText += "\""+stereos+"\" ";
					Event event = trigger.getEvent();
					if(event != null){
						if(!event.eAdapters().contains(_adapter))
							event.eAdapters().add(_adapter);
						
						stereos = "";
						it = event.getAppliedStereotypes().iterator();
						while(it.hasNext()){
							String st = ((Stereotype)it.next()).getName();
							st = st.substring(0, 1).toUpperCase()+st.substring(1);
							stereos += st;
						}
						if((stereos != "") && isStereotypesDisplayed)
							triggersText += "\""+stereos+"\" ";
						if(event instanceof CallEvent)
							triggersText += com.cea.papyrus.umlutils.Operation.getSignature(((CallEvent)event).getOperation(), false)+", ";
						else if(event instanceof SignalEvent)
							triggersText += ((SignalEvent)event).getSignal().getName()+", ";
						else if(event instanceof AnyReceiveEvent)
							triggersText += "all, ";
						else if(event instanceof ChangeEvent){
							ChangeEvent changeEvent = (ChangeEvent)event;
							if((changeEvent.getChangeExpression() != null) && (changeEvent.getChangeExpression() instanceof LiteralString))
								triggersText += "when "+changeEvent.getChangeExpression().stringValue()+", ";
							else
								triggersText += "when "+changeEvent.getName()+", ";
						}		
						else if(event instanceof TimeEvent){
							TimeEvent timeEvent = (TimeEvent)event;
							if((timeEvent.getWhen() != null) && (timeEvent.getWhen() instanceof LiteralString))
								triggersText += timeEvent.getWhen().stringValue()+", ";
							else
								triggersText += timeEvent.getName()+", ";
						}		
					}
					else{
						triggersText += trigger.getName()+", ";
					}
				}
				triggersText = triggersText.substring(0, triggersText.length()-2);
			}

			//update display properties
			getGuardAndAllDisplayProperties(getGraphNode());
			
			String toShow = "";
			if(isTriggersDisplayed)
				toShow += triggersText+" ";
			if(isGuardDisplayed)
				toShow += guardText+" ";
			if(isEffectDisplayed)
				toShow += effectText;
			f.setText(toShow.trim());
		}
		f.setVisible(isVisible());
	}
}
